package com.christina.engine.state;

import com.christina.engine.state.model.StateContext;
import com.christina.engine.state.model.StateTransitionResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * 对话状态管理器
 * 负责管理对话状态的转换和生命周期
 * 
 * @author Christina
 */
@Slf4j
@Component
public class ConversationStateManager {
    
    private final Map<String, ConversationState> registeredStates = new ConcurrentHashMap<>();
    private final Map<String, StateContext> activeContexts = new ConcurrentHashMap<>();
    private final Map<String, ConversationState> currentStates = new ConcurrentHashMap<>();
    private final ScheduledExecutorService timeoutExecutor = Executors.newScheduledThreadPool(2);
    
    /**
     * 注册对话状态
     * 
     * @param state 对话状态
     */
    public void registerState(ConversationState state) {
        if (state == null) {
            throw new IllegalArgumentException("State cannot be null");
        }
        
        String stateName = state.getStateName();
        if (stateName == null || stateName.trim().isEmpty()) {
            throw new IllegalArgumentException("State name cannot be null or empty");
        }
        
        registeredStates.put(stateName, state);
        log.info("Registered conversation state: {}", stateName);
    }
    
    /**
     * 注销对话状态
     * 
     * @param stateName 状态名称
     */
    public void unregisterState(String stateName) {
        ConversationState removed = registeredStates.remove(stateName);
        if (removed != null) {
            log.info("Unregistered conversation state: {}", stateName);
        }
    }
    
    /**
     * 开始新的对话会话
     * 
     * @param sessionId 会话ID
     * @param initialStateName 初始状态名称
     * @param context 状态上下文
     * @return 转换结果
     */
    public StateTransitionResult startSession(String sessionId, String initialStateName, StateContext context) {
        if (sessionId == null || sessionId.trim().isEmpty()) {
            throw new IllegalArgumentException("Session ID cannot be null or empty");
        }
        
        ConversationState initialState = registeredStates.get(initialStateName);
        if (initialState == null) {
            return StateTransitionResult.failure("Initial state not found: " + initialStateName);
        }
        
        // 设置上下文
        context.setSessionId(sessionId);
        context.setStateStartTime(LocalDateTime.now());
        context.updateLastActivityTime();
        
        // 保存上下文和当前状态
        activeContexts.put(sessionId, context);
        currentStates.put(sessionId, initialState);
        
        // 进入初始状态
        StateTransitionResult result = initialState.onEnter(context);
        
        // 处理转换结果
        processTransitionResult(sessionId, result, context);
        
        // 设置超时监控
        scheduleTimeoutCheck(sessionId, initialState);
        
        log.info("Started conversation session: {} with initial state: {}", sessionId, initialStateName);
        return result;
    }
    
    /**
     * 处理消息
     * 
     * @param sessionId 会话ID
     * @param message 消息内容
     * @return 转换结果
     */
    public StateTransitionResult handleMessage(String sessionId, String message) {
        StateContext context = activeContexts.get(sessionId);
        if (context == null) {
            return StateTransitionResult.failure("Session not found: " + sessionId);
        }
        
        ConversationState currentState = currentStates.get(sessionId);
        if (currentState == null) {
            return StateTransitionResult.failure("Current state not found for session: " + sessionId);
        }
        
        // 更新上下文
        context.setCurrentMessage(message);
        context.updateLastActivityTime();
        
        try {
            // 处理消息
            StateTransitionResult result = currentState.handleMessage(message, context);
            
            // 处理转换结果
            processTransitionResult(sessionId, result, context);
            
            return result;
            
        } catch (Exception e) {
            log.error("Error handling message in session: {}", sessionId, e);
            return StateTransitionResult.failure("Error processing message: " + e.getMessage());
        }
    }
    
    /**
     * 转换到指定状态
     * 
     * @param sessionId 会话ID
     * @param targetStateName 目标状态名称
     * @param reason 转换原因
     * @return 转换结果
     */
    public StateTransitionResult transitionTo(String sessionId, String targetStateName, String reason) {
        StateContext context = activeContexts.get(sessionId);
        if (context == null) {
            return StateTransitionResult.failure("Session not found: " + sessionId);
        }
        
        ConversationState currentState = currentStates.get(sessionId);
        ConversationState targetState = registeredStates.get(targetStateName);
        
        if (targetState == null) {
            return StateTransitionResult.failure("Target state not found: " + targetStateName);
        }
        
        // 检查是否可以转换
        if (currentState != null && !currentState.canTransitionTo(targetState, context)) {
            return StateTransitionResult.failure("Cannot transition from " + 
                    currentState.getStateName() + " to " + targetStateName);
        }
        
        return performStateTransition(sessionId, currentState, targetState, reason, context);
    }
    
    /**
     * 结束会话
     * 
     * @param sessionId 会话ID
     * @param reason 结束原因
     * @return 转换结果
     */
    public StateTransitionResult endSession(String sessionId, String reason) {
        StateContext context = activeContexts.get(sessionId);
        ConversationState currentState = currentStates.get(sessionId);
        
        StateTransitionResult result = StateTransitionResult.endConversation(
                "Conversation ended: " + (reason != null ? reason : "User request"));
        
        if (currentState != null && context != null) {
            try {
                // 退出当前状态
                currentState.onExit(context);
            } catch (Exception e) {
                log.warn("Error exiting state during session end: {}", sessionId, e);
            }
        }
        
        // 清理会话数据
        activeContexts.remove(sessionId);
        currentStates.remove(sessionId);
        
        log.info("Ended conversation session: {} with reason: {}", sessionId, reason);
        return result;
    }
    
    /**
     * 获取会话的当前状态
     * 
     * @param sessionId 会话ID
     * @return 当前状态，如果会话不存在返回null
     */
    public ConversationState getCurrentState(String sessionId) {
        return currentStates.get(sessionId);
    }
    
    /**
     * 获取会话的状态上下文
     * 
     * @param sessionId 会话ID
     * @return 状态上下文，如果会话不存在返回null
     */
    public StateContext getStateContext(String sessionId) {
        return activeContexts.get(sessionId);
    }
    
    /**
     * 检查会话是否存在
     * 
     * @param sessionId 会话ID
     * @return 是否存在
     */
    public boolean hasSession(String sessionId) {
        return activeContexts.containsKey(sessionId);
    }
    
    /**
     * 获取所有活跃的会话ID
     * 
     * @return 活跃的会话ID集合
     */
    public Set<String> getActiveSessionIds() {
        return new HashSet<>(activeContexts.keySet());
    }
    
    /**
     * 处理转换结果
     * 
     * @param sessionId 会话ID
     * @param result 转换结果
     * @param context 状态上下文
     */
    private void processTransitionResult(String sessionId, StateTransitionResult result, StateContext context) {
        if (result == null) {
            return;
        }
        
        // 更新状态数据
        if (result.getStateDataUpdates() != null) {
            result.getStateDataUpdates().forEach(context::setStateData);
        }
        
        // 处理状态转换
        if (result.hasStateTransition()) {
            ConversationState currentState = currentStates.get(sessionId);
            ConversationState nextState = result.getNextState();
            
            performStateTransition(sessionId, currentState, nextState, result.getReason(), context);
        }
        
        // 处理会话结束
        if (result.shouldEnd()) {
            endSession(sessionId, result.getReason());
        }
        
        // 处理重试
        if (result.shouldRetry() && context.canRetry()) {
            context.incrementRetryCount();
            scheduleRetry(sessionId, result.getRetryDelayMillis());
        }
    }
    
    /**
     * 执行状态转换
     * 
     * @param sessionId 会话ID
     * @param fromState 源状态
     * @param toState 目标状态
     * @param reason 转换原因
     * @param context 状态上下文
     * @return 转换结果
     */
    private StateTransitionResult performStateTransition(String sessionId, 
                                                       ConversationState fromState, 
                                                       ConversationState toState, 
                                                       String reason, 
                                                       StateContext context) {
        try {
            // 退出当前状态
            if (fromState != null) {
                StateTransitionResult exitResult = fromState.onExit(context);
                if (!exitResult.isSuccessful()) {
                    return exitResult;
                }
            }
            
            // 更新状态历史
            String fromStateName = fromState != null ? fromState.getStateName() : "null";
            String toStateName = toState.getStateName();
            context.addStateHistory(fromStateName, toStateName, reason);
            
            // 更新当前状态
            currentStates.put(sessionId, toState);
            context.setStateStartTime(LocalDateTime.now());
            context.resetRetryCount();
            
            // 进入新状态
            StateTransitionResult enterResult = toState.onEnter(context);
            
            // 设置新的超时监控
            scheduleTimeoutCheck(sessionId, toState);
            
            log.debug("State transition completed: {} -> {} for session: {}", 
                    fromStateName, toStateName, sessionId);
            
            return enterResult;
            
        } catch (Exception e) {
            log.error("Error during state transition for session: {}", sessionId, e);
            return StateTransitionResult.failure("State transition failed: " + e.getMessage());
        }
    }
    
    /**
     * 安排超时检查
     * 
     * @param sessionId 会话ID
     * @param state 状态
     */
    private void scheduleTimeoutCheck(String sessionId, ConversationState state) {
        long timeoutMillis = state.getTimeoutMillis();
        if (timeoutMillis > 0) {
            timeoutExecutor.schedule(() -> {
                handleStateTimeout(sessionId, state);
            }, timeoutMillis, TimeUnit.MILLISECONDS);
        }
    }
    
    /**
     * 处理状态超时
     * 
     * @param sessionId 会话ID
     * @param state 状态
     */
    private void handleStateTimeout(String sessionId, ConversationState state) {
        StateContext context = activeContexts.get(sessionId);
        ConversationState currentState = currentStates.get(sessionId);
        
        // 检查状态是否仍然是当前状态且确实超时
        if (context != null && currentState == state && context.isTimeout(state.getTimeoutMillis())) {
            try {
                StateTransitionResult result = state.onTimeout(context);
                processTransitionResult(sessionId, result, context);
                
                log.info("Handled timeout for session: {} in state: {}", sessionId, state.getStateName());
            } catch (Exception e) {
                log.error("Error handling timeout for session: {}", sessionId, e);
                endSession(sessionId, "Timeout handling error");
            }
        }
    }
    
    /**
     * 安排重试
     * 
     * @param sessionId 会话ID
     * @param delayMillis 延迟时间
     */
    private void scheduleRetry(String sessionId, Long delayMillis) {
        long delay = delayMillis != null ? delayMillis : 1000; // 默认1秒延迟
        
        timeoutExecutor.schedule(() -> {
            StateContext context = activeContexts.get(sessionId);
            if (context != null) {
                // 重新处理最后的消息
                handleMessage(sessionId, context.getCurrentMessage());
            }
        }, delay, TimeUnit.MILLISECONDS);
    }
    
    /**
     * 获取管理器统计信息
     * 
     * @return 统计信息
     */
    public Map<String, Object> getStatistics() {
        Map<String, Object> stats = new HashMap<>();
        stats.put("registeredStates", registeredStates.size());
        stats.put("activeSessions", activeContexts.size());
        stats.put("stateNames", new ArrayList<>(registeredStates.keySet()));
        
        // 统计各状态的会话数量
        Map<String, Integer> stateDistribution = new HashMap<>();
        currentStates.values().forEach(state -> {
            String stateName = state.getStateName();
            stateDistribution.put(stateName, stateDistribution.getOrDefault(stateName, 0) + 1);
        });
        stats.put("stateDistribution", stateDistribution);
        
        return stats;
    }
    
    /**
     * 清理所有会话
     */
    public void clearAllSessions() {
        Set<String> sessionIds = new HashSet<>(activeContexts.keySet());
        for (String sessionId : sessionIds) {
            endSession(sessionId, "Manager cleanup");
        }
        log.info("Cleared all conversation sessions");
    }
    
    /**
     * 关闭管理器
     */
    public void shutdown() {
        clearAllSessions();
        timeoutExecutor.shutdown();
        try {
            if (!timeoutExecutor.awaitTermination(5, TimeUnit.SECONDS)) {
                timeoutExecutor.shutdownNow();
            }
        } catch (InterruptedException e) {
            timeoutExecutor.shutdownNow();
            Thread.currentThread().interrupt();
        }
        log.info("Conversation state manager shutdown completed");
    }
}